package com.anxinr.frame;

import com.anxinr.config.ExecutorConfig;
import com.anxinr.exception.MyFrameException;
import com.anxinr.function.LambdaInterface;
import com.anxinr.function.ThreadFunctionInterface;
import org.omg.CORBA.Current;

import java.lang.reflect.Field;
import java.util.Calendar;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.ArrayBlockingQueue;

/**
 * @author : anxinr
 * @date : 2022/10/12 10:56
 */
public class MyTaskThreadPoolExecutor implements LambdaInterface, ThreadFunctionInterface {
    /**我的线程池框架对象*/
    private static MyTaskThreadPoolExecutor taskThreadPoolExecutor = null ;
    /**任务阻塞队列*/
    private static ArrayBlockingQueue taskQueue ;
    /**核心线程队列*/
    private static ArrayBlockingQueue workQueue ;

    private MyTaskThreadPoolExecutor(){
        /**初始化核心线程工作池*/
        initWorkQueue() ;
        /**开启异步长轮询*/
        new Thread(()->{
            workPlace() ;
        }).start();
    }

    private void workPlace() {
        /**设置长轮询时间  实现结束后删除这行代码*/
        Calendar instance = Calendar.getInstance();
        Long startTime = System.currentTimeMillis() ;
        instance.setTime(new Date(startTime));
        instance.add(Calendar.SECOND,15);
        long endTime = instance.getTime().getTime();
//        endTime >= System.currentTimeMillis()
        while (true){
            Runnable runnable = null;
            /**保证work队列中的活跃线程*/
            workQueueKeepActive() ;
            try {
                if (taskQueue.size() > 0) {
                    runnable = (Runnable) taskQueue.take() ;
                    /**查看核心线程队列是否有空闲的线程*/
                    if (workQueue.size() > 0) {
                        execute(runnable);
                    }else {
                        /**如果没有空闲的核心线程，那么就继续去访问是否有核心线程，开始下一轮轮询*/
                        taskQueue.add(runnable) ;
                        continue;
                    }
                }
            } catch (Exception e) {
                if (!Objects.isNull(runnable)){
                    taskQueue.add(runnable) ;
                }
                e.printStackTrace();
            }
        }
    }

    /**
     * 保证核心线程数量
     */
    private void workQueueKeepActive() {
        /**如果存活的核心线程 小于 配置中的核心线程数  添加新的核心线程*/
        synchronized (this) {
            if (workQueue.size() < ExecutorConfig.coreThread) {
                for (int i = 1; i < ExecutorConfig.coreThread - workQueue.size(); i++) {
                    for (int i1 = 1; i1 < workQueue.size(); i1++) {
                        for (Object o : workQueue) {
                            Thread worker = (Thread) o;
                            if (!(ExecutorConfig.prefix + i1).equals(worker.getName())) {
                                /**添加到核心线程池  在此时，还必须添加同步锁来保证数据的安全性因为 size 是线程不安全的并且线程之间是不可见的 (没有 volatile 来修饰)*/
                                if (workQueue.size() < ExecutorConfig.coreThread) {
                                    /** FIXME 线程名称BUG */
                                    workQueue.add(new Thread(ExecutorConfig.prefix + i1));
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    /**
     * 初始化核心线程池
     */
    private void initWorkQueue() {
        for (Integer i = 0; i < ExecutorConfig.coreThread; i++) {
            workQueue.add(new Thread(ExecutorConfig.prefix + i)) ;
        }
    }

    /**
     * 获取线程框架对象
     * @param maxTaskNumber
     * @param coreThread
     * @return MyTaskThreadPoolExecutor
     * @throws Exception
     */
    public static MyTaskThreadPoolExecutor getInstance(Integer maxTaskNumber,Integer coreThread) throws Exception {
        if (maxTaskNumber <= 0){
            throw new MyFrameException("初始化任务队列失败！") ;
        }
        if (coreThread <= 0){
            throw new MyFrameException("初始化核心线程队列失败！") ;
        }
        taskQueue = new ArrayBlockingQueue(maxTaskNumber) ;
        workQueue = new ArrayBlockingQueue(coreThread) ;
        /**同步到配置*/
        ExecutorConfig.maxTaskNumber = maxTaskNumber ;
        ExecutorConfig.coreThread = coreThread ;
        if (Objects.isNull(taskThreadPoolExecutor)){
            return new MyTaskThreadPoolExecutor() ;
        }
        return taskThreadPoolExecutor;
    }

    /**
     * 获取线程框架对象
     * @return MyTaskThreadPoolExecutor
     */
    public static MyTaskThreadPoolExecutor getInstance() {
        taskQueue = new ArrayBlockingQueue(ExecutorConfig.maxTaskNumber) ;
        workQueue = new ArrayBlockingQueue(ExecutorConfig.coreThread) ;
        if (Objects.isNull(taskThreadPoolExecutor)){
            return new MyTaskThreadPoolExecutor() ;
        }
        return taskThreadPoolExecutor;
    }

    @Override
    public void execute(Runnable thread) {
        try {
            Thread take = (Thread) workQueue.take();
            Field target = take.getClass().getDeclaredField("target");
            target.setAccessible(true);
            target.set(take,thread);
            take.start();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public Integer getCoreThreadNumber() {
        return workQueue.size();
    }

    @Override
    public Integer getTaskQueueTaskNumber() {
        return taskQueue.size();
    }

    @Override
    public boolean addTaskToQueue(Runnable thread) {
        taskQueue.add(thread) ;
        try {
            synchronized (Thread.currentThread()){
                Thread.currentThread().wait(10L);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            return false ;
        }
        return true;
    }
}
